package com.xpec.c4.game.utility;

import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.xpec.c4.game.common.Helper;
import com.xpec.c4.service.module.ModuleServer;
import com.xpec.c4.service.module.ServerProperties;
/**
 * 產生 3個int 的 uuid , 建議如果需要大量操作時可以採用這個UUID在compare & 封包傳送運算較快,<br>
 * 但是toString到DB可能會比較長一點
 * 
 * @author Wilson_Wu
 *
 */
public class GUIDFactory {
	/** log4j object */
	private static final Log log = LogFactory.getLog(GUIDFactory.class);
	
	/**
	 * 伺服器組id
	 */
	private static int worldId = ServerProperties.getInt("game_group_id", -1);
	/**
	 * process id : module start set
	 */
	private static int processId = -1;
	/**
	 * 流水號
	 */
	private static AtomicInteger seq = new AtomicInteger(Helper.randomInt());
	
	private static AtomicInteger seq2 = new AtomicInteger();

	/**
	 * 96 : 12 world , 10 process, 10 type, 32 time , 32 seq
	 * @param type
	 * @see com.xpec.c4.game.utility.GUIDType
	 * @return
	 */
	static public GUID createUUID(int type){
		if(worldId < 0 || processId < 0) return null;
		
		GUID guid = new GUID();
		// 組隨機值
		guid.firstId = GameUtility.randomInt(0, Integer.MAX_VALUE - 1);

		// 組time
		guid.secId   = (int) (System.currentTimeMillis() / 1000L);

		// 組seq
		guid.lastId  =  seq.incrementAndGet();	
		return guid;
	}
	/**
	 * 產生一組特別GUID (全部給使用者指定)
	 * @return
	 */
	static public GUID createConstUUID(int worldId, int processId , int type , int time, int lastId){
		GUID guid = new GUID();
		// 組world
		guid.firstId |= worldId << 20; 
		// 組process
		guid.firstId |= (0xFFC00 & (processId << 10));
		
		guid.firstId |= (0x3ff & type);
		// 組time
		guid.secId   = time;
		// 組seq
		guid.lastId  =  lastId;	
		return guid;
	}
	public static long getLogId() {
		return getLogId(System.currentTimeMillis());
	}
	
	public static long getLogId(long currentTimeMills) {
		if(worldId < 0 || processId < 0) throw new RuntimeException("");
		
		long result = 0;
		
		//worldid 10 bits
		result |=  (0x3ff & (long)worldId) << 54;
		
		//pid 10 bits
		result |=  (0x3ff & (long)processId) << 44;
		
		//timestamp of second 27 bits
		long t = (0x7ffffff & (currentTimeMills/1000l));
		result |=  (t << 17);
		
		//seq 17 bits
		result |= (0x1ffff & (long)seq2.getAndIncrement());
		
		return result;
	}
	
	public static void setProcessId(String serverName) {
		if(serverName == null) return;
		if(serverName.equals(ModuleServer.ALL_MODULE_START_UP))
			GUIDFactory.processId = 999;
		else{
			try{
				GUIDFactory.processId = Integer.parseInt( serverName.substring(6));
			}
			catch(Exception e){
				if (log.isErrorEnabled()) {
					log.error("setProcessId fail.", e);
				}
			}
		}
	}
	
	
	public static int getWorldId() {
		return worldId;
	}
	public static void setWorldId(int worldId) {
		GUIDFactory.worldId = worldId;
	}
	public static int getProcessId() {
		return processId;
	}
	public static void setProcessId(int processId) {
		GUIDFactory.processId = processId;
	}


	//相容舊版的GUID相關功能
	/**
	 * 随机产生器
	 */
	//private static final Random random = new Random();

	/**
	 * 唯一ID计数器
	 */
	private static int uniqueIDCount = 0;


	/**
	 * 生成一个近似全局唯一的ID
	 * 
	 * @return
	 */
	public static String genUniqueID() {
		String lRetID = "";
		long lCurTime = System.currentTimeMillis();
		lRetID += lCurTime & 0xffffff;
		for (int i = 0; i < 6; i++) {
			lRetID += genLetterNumber();
		}
		lRetID += uniqueIDCount;
		uniqueIDCount++;
		return lRetID;
	}
	public static String genUniqueID(String type) {
		return type + "_" + genUniqueID();
	}
	/**
	 * 随机生成一个字母（大小写）或数字
	 * 
	 * @return
	 */
	public static String genLetterNumber() {
		int lRandomNumber = Helper.randomInt(0, 62);
		if (lRandomNumber >= 0 && lRandomNumber <= 9) {
			return String.valueOf((char) (lRandomNumber + 48));
		} else if (lRandomNumber >= 10 && lRandomNumber <= 35) {
			return String.valueOf((char) (lRandomNumber - 10 + 65));
		} else {
			return String.valueOf((char) (lRandomNumber - 36 + 97));
		}
	}

	public static String mailGuid() {
		return "mail_" + genUniqueID();
	}
}
